﻿using System;
using System.Collections.Generic;
using System.Data;
using TidyBlog.Entity;
using TidyBlog.Data;

namespace TidyBlog.DAL
{
    /// <summary>
    /// 文章数据访问层
    /// </summary>
    public class ArticleDAL
    {
        /// <summary>
        /// 创建文章记录
        /// </summary>
        /// <param name="article">文章</param>
        /// <returns>文章编号</returns>
        public static int Create(Article article)
        {
            object autoId;
            SimpleORM<Article>.Insert(article, out autoId);

            return Convert.ToInt32(autoId);
        }

        /// <summary>
        /// 更新文章记录
        /// </summary>
        /// <param name="article">文章</param>
        /// <returns>影响的记录数</returns>
        public static int Update(Article article)
        {
            return SimpleORM<Article>.Update(article);
        }

        /// <summary>
        /// 读取文章
        /// </summary>
        /// <param name="articleId">文章编号</param>
        /// <returns>文章</returns>
        public static Article Read(int articleId)
        {
            return SimpleORM<Article>.Read(
                new Article()
                {
                    ArticleId = articleId
                }
            );
        }

        /// <summary>
        /// 删除文章
        /// </summary>
        /// <param name="userId">文章编号</param>
        /// <returns>影响的行数</returns>
        public static int Delete(int articleId)
        {
            return SimpleORM<Article>.Delete(
                new Article()
                {
                    ArticleId = articleId
                }
            );
        }
        
        /// <summary>
        /// 检查指定编号的文章记录是否存在
        /// </summary>
        /// <param name="articleId">文章编号</param>
        /// <returns>指定编号的文章记录是否存在</returns>
        public static bool IsExist(int articleId)
        {
            var cmd = DbHelper.CreateCommand((new SelectCommand(SimpleORM<Article>.TableName))
                .Select("COUNT(*)")
                .Where(new WhereCondition("ArticleId", articleId.ToString()))
                .ToString()
            );

            return Convert.ToInt32(DbHelper.ExecuteScalar(cmd)) > 0;
        }

        /// <summary>
        /// 搜索文章
        /// </summary>
        /// <param name="queryParams">查询参数</param>
        /// <param name="pageSize">每页显示记录数</param>
        /// <param name="currentPage">当前页</param>
        /// <param name="sortColumns">排序列</param>
        /// <returns>搜索结果</returns>
        public static DataPaging<Article> List(Dictionary<string, string> queryParams, ushort pageSize, int currentPage, IEnumerable<SortColumn> sortColumns)
        {
            var pagingHelper = DbHelper.Provider.CreatePagingHelper<Article>();
            var whereConditions = new List<WhereCondition>();

            if (queryParams != null)
            {
                // 标题
                if (queryParams.ContainsKey("title") && !String.IsNullOrEmpty(queryParams["title"]))
                {
                    whereConditions.Add(new WhereCondition("Title") { Operator = WhereOperator.LIKE });
                    DbHelper.AttachParams(pagingHelper.Cmd,
                        DbHelper.CreateParam("Title", "%" + queryParams["title"] + "%", DbType.String)
                    );
                }
                // 分类编号
                if (queryParams.ContainsKey("categoryid") && !String.IsNullOrEmpty(queryParams["categoryid"]) && !queryParams["categoryid"].Equals("0"))
                {
                    whereConditions.Add(new WhereCondition("CategoryId"));
                    SimpleORM<Article>.AttachParam(pagingHelper.Cmd, "CategoryId", queryParams["categoryid"]);
                }
                // 最小权重
                if (queryParams.ContainsKey("minweight") && !String.IsNullOrEmpty(queryParams["minweight"]))
                {
                    whereConditions.Add(new WhereCondition()
                    {
                        Column = "Weight",
                        Operator = WhereOperator.GREATER_OR_EQUAL,
                        Value = "MinWeight"
                    });
                    SimpleORM<Article>.AttachParam(pagingHelper.Cmd, "CategoryId", "MinWeight", queryParams["minweight"]);
                }
            }
            pagingHelper.SQLCommand.OrderBy(sortColumns).Where(whereConditions);

            return pagingHelper.Execute(pageSize, currentPage);
        }

        /// <summary>
        /// 获取同分类下的下一篇文章
        /// </summary>
        /// <param name="refArticle">参照文章</param>
        /// <param name="isNext">是否下一篇文章</param>
        /// <param name="minWeight">最小权重</param>
        /// <returns>同分类下的下一篇文章</returns>
        public static Article GetAdjacent(Article refArticle, bool isNext, byte minWeight)
        {
            // TODO 排序方式
            var cmd = DbHelper.CreateCommand((new SelectCommand(SimpleORM<Article>.TableName))
                .Select("*")
                .Top(1)
                .OrderBy(new SortColumn()
                {
                    Column = "ArticleId",
                    OrderWay = isNext ? OrderWay.ASC : OrderWay.DESC
                })
                .Where(new[]
                {
                    new WhereCondition("CategoryId", refArticle.CategoryId.ToString()),
                    new WhereCondition("ArticleId", refArticle.ArticleId.ToString())
                    {
                        Operator = isNext ? WhereOperator.GREATER : WhereOperator.LESS
                    },
                    new WhereCondition("Weight", minWeight.ToString())
                    {
                        Operator = WhereOperator.GREATER_OR_EQUAL
                    }
                })
                .ToString()
            );

            return SimpleORM<Article>.DataReaderToEntity(DbHelper.ExecuteReader(cmd));
        }

        /// <summary>
        /// 增加文章查看数
        /// </summary>
        /// <param name="articleId">文章编号</param>
        /// <returns>影响的记录数</returns>
        public static int AddViewCount(int articleId)
        {
            var cmd = DbHelper.CreateCommand((new UpdateCommand(SimpleORM<Article>.TableName))
                .Set(new ColumnValuePair("ViewCount", "ViewCount + 1"))
                .Where(new WhereCondition("ArticleId", articleId.ToString()))
                .ToString()
            );

            return DbHelper.ExecuteNonQuery(cmd);
        }

        /// <summary>
        /// 按分类列出文章
        /// </summary>
        /// <param name="categoryId">文章编号</param>
        /// <param name="minWeight">最小权重</param>
        /// <param name="pageSize">每页文章数</param>
        /// <param name="currentPage">当前页</param>
        /// <returns>文章列表</returns>
        public static DataPaging<Article> ListByCategory(int categoryId, byte minWeight, ushort pageSize, int currentPage)
        {
            var queryParams = new Dictionary<string, string>();
            queryParams.Add("minweight", minWeight.ToString());
            queryParams.Add("categoryid", categoryId.ToString());

            return List(queryParams, pageSize, currentPage, null);
        }

        /// <summary>
        /// 获取按查看数排序的文章列表
        /// </summary>
        /// <param name="categoryId">分类编号</param>
        /// <param name="minWeight">最小权重</param>
        /// <param name="pageSize">列出数量</param>
        /// <returns>文章列表</returns>
        public static Article[] GetTopView(int categoryId, byte minWeight, byte pageSize)
        {
            var whereConditions = new List<WhereCondition>();
            whereConditions.Add(new WhereCondition("Weight", minWeight.ToString())
            {
                Operator = WhereOperator.GREATER_OR_EQUAL
            });
            if (categoryId != 0)
            {
                whereConditions.Add(new WhereCondition("CategoryId", categoryId.ToString()));
            }

            var selectCommand = new SelectCommand(SimpleORM<Article>.TableName)
                .Select(SimpleORM<Article>.ListColumns)
                .Top(pageSize)
                .OrderBy(new[]
                {
                    new SortColumn()
                    {
                        Column = "ViewCount",
                        OrderWay = OrderWay.DESC
                    }
                })
                .Where(whereConditions);

            return SimpleORM<Article>.DataReaderToEntityList(
                DbHelper.ExecuteReader(DbHelper.CreateCommand(selectCommand.ToString()))
            ).ToArray();
        }

        /// <summary>
        /// 获取按权重、发表时间反序排列的大于某个权重值的文章
        /// </summary>
        /// <param name="minWeight">权重</param>
        /// <returns>推荐文章列表</returns>
        public static Article[] GetByMinWeight(byte minWeight)
        {
            var selectCommand = new SelectCommand(SimpleORM<Article>.TableName)
                .Select(SimpleORM<Article>.ListColumns)
                .OrderBy(new[]
                {
                    new SortColumn()
                    {
                        Column = "Weight",
                        OrderWay = OrderWay.DESC
                    },
                    new SortColumn()
                    {
                        Column = "PostTime",
                        OrderWay = OrderWay.DESC
                    }
                })
                .Where(new[]
                {
                    new WhereCondition("Weight", minWeight.ToString())
                    {
                        Operator = WhereOperator.GREATER_OR_EQUAL
                    }
                });

            return SimpleORM<Article>.DataReaderToEntityList(
                DbHelper.ExecuteReader(DbHelper.CreateCommand(selectCommand.ToString()))
            ).ToArray();
        }
    }
}
